package it.polimi.swKnights.SWIMv2.ejb.abilityManager;

import it.polimi.swKnights.SWIMv2.ejb.authentication.LoginHandlerLocal;
import it.polimi.swKnights.SWIMv2.ejb.entityBeans.Ability;
import it.polimi.swKnights.SWIMv2.ejb.entityBeans.RegisteredUser;
import it.polimi.swKnights.SWIMv2.ejb.exceptions.AbilityNotFoundException;
import it.polimi.swKnights.SWIMv2.ejb.exceptions.InvalidLoginPrivilegesException;
import it.polimi.swKnights.SWIMv2.ejb.exceptions.LoginFailException;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 * Session Bean implementation class AbilityHandler
 */
@Stateless
public class AbilityHandler implements AbilityHandlerRemote
{
	@PersistenceContext(unitName = "swimv2-manager")
	private EntityManager manager;

	@EJB
	private LoginHandlerLocal loginManager;

	@Override
	public Map<String, String> getAbilities()
	{
		Map<String, String> approvedAbilities = new HashMap<String, String>();

		Query q = this.manager.createQuery("FROM Ability a "
				+ "WHERE a.confirmed=true ");

		List<?> queryList = q.getResultList();

		for (Object item : queryList)
		{
			Ability ability = (Ability) item;
			approvedAbilities.put(ability.getName(), ability.getDescription());
		}

		return approvedAbilities;
	}

	@Override
	public void addAbility(String userName, String password, String ability)
			throws LoginFailException, InvalidLoginPrivilegesException,
			AbilityNotFoundException
	{
		this.loginManager.checkLoginDataAndPrivileges(userName, password,
				RegisteredUser.class);
		this.handleOperation(true, userName, ability);
	}

	@Override
	public void removeAbility(String userName, String password, String ability)
			throws LoginFailException, InvalidLoginPrivilegesException,
			AbilityNotFoundException
	{
		this.loginManager.checkLoginDataAndPrivileges(userName, password,
				RegisteredUser.class);
		this.handleOperation(false, userName, ability);
	}

	@Override
	public Map<String, String> getUserabilities(String userName)
	{
		RegisteredUser user = this.manager.find(RegisteredUser.class, userName);

		Map<String, String> abilityMap = new HashMap<String, String>();

		if (user != null)
		{
			Set<Ability> abilities = user.getAbilities();
			for (Ability ability : abilities)
			{
				abilityMap.put(ability.getName(), ability.getDescription());
			}
		}

		return abilityMap;
	}

	private void handleOperation(boolean add, String userName,
			String abilityName) throws AbilityNotFoundException
	{
		RegisteredUser user = this.manager.find(RegisteredUser.class, userName);
		Ability ability = this.manager.find(Ability.class, abilityName);

		if (ability == null)
		{
			throw new AbilityNotFoundException();
		}
		else if(!ability.isConfirmed())
		{
			throw new AbilityNotFoundException();
		}

		if (add)
		{
			user.addAbility(ability);
		}
		else
		{
			user.removeAbility(ability);
		}

		this.manager.persist(user);
	}
}
